package game;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.Point2D;

public class Calculator extends Scene{
	
	Background bg;

	static Point curS;
	static int type, mNumber;
	
	ParColchete[] parColchetes = new ParColchete[3];
	SinaisOperacao[] sinaisOperacao = new SinaisOperacao[5];
	Font font1 = new Font("Arial", Font.ROMAN_BASELINE, 35);
	String typeMatriz;
	FontMetrics fm;
	public int fontWidth;
	
	static MatrixManager mm;

	
	public Calculator()
	{
		curS = null;
		type = MatrixType.getMatrixType().length;
		mm = MatrixManager.getInstace();
		typeMatriz = MatrixOperation.getTypeMatriz() + "  -  " + type + " x " + type;
		bg = new Background("/images/bg_Calculator.png", new Point2D.Double(0,0), new Point2D.Double(800,600));
		
		CriarColchetes();
		mm.CriarMatrix(parColchetes[0], parColchetes[1], parColchetes[2]);
	}

	@Override
	public void update() {
		
		//Update Buttons and Matrix
		switch (mNumber)
		{
			case 1:
				ButtonManager.getInstace().UpdateButtonMatrix(mm.matrixF, curS);
				break;
			case 2:
				ButtonManager.getInstace().UpdateButtonMatrix(mm.matrixS, curS);
				break;
		}
		
		if (AllFilled())
		{
			switch(MatrixOperation.getTypeOperation())
			{
				case SOMAR:
					mm.AddNaMatrizResult(CalculosMatriz.getInstace().SomarMatrizes(mm.ReturnMatrizEmDouble(mm.matrixF), mm.ReturnMatrizEmDouble(mm.matrixS), type, type));
					break;
					
				case MULTIPLICAR_MATRIZES:
					mm.AddNaMatrizResult(CalculosMatriz.getInstace().MultiplicarPorMatriz(mm.ReturnMatrizEmDouble(mm.matrixF), mm.ReturnMatrizEmDouble(mm.matrixS)));
					break;
					
				case OPOSTA:
					mm.AddNaMatrizResult(CalculosMatriz.getInstace().OpostarMatriz(mm.ReturnMatrizEmDouble(mm.matrixS), type, type));
					break;
					
				case TRANSPOSTA:
					mm.AddNaMatrizResult(CalculosMatriz.getInstace().TransportarMatriz(mm.ReturnMatrizEmDouble(mm.matrixS)));
					break;
					
				case SUBTRAIR:
					mm.AddNaMatrizResult(CalculosMatriz.getInstace().DiminuirMatrizes(mm.ReturnMatrizEmDouble(mm.matrixF), mm.ReturnMatrizEmDouble(mm.matrixS), type, type));
					break;
					
				case MULTIPLICAR_NUMERO:
					mm.AddNaMatrizResult(CalculosMatriz.getInstace().MultiplicarPorNumero(mm.ReturnMatrizEmDouble(mm.matrixF), mm.ReturnMatrizEmDouble(mm.matrixS), type, type));
					break;
					
				case DETERMINANTE:
					mm.AddNaMatrizResult(CalculosMatriz.getInstace().DeterminanteMatriz(mm.ReturnMatrizEmDouble(mm.matrixS)));
					break;
			}
		}
		else 
		{
			if(mm.matrixR.length != 1)
			{
				for (int x = 0; x < type; x++)
					for (int y = 0; y < type; y++)
					{
						
						mm.matrixR[x][y].value = null;
					}
			}
			else
				mm.matrixR[0][0].value = null;
		}
		
		for (int x = 0; x < type; x++)
			for (int y = 0; y < type; y++)
			{
				if(mm.matrixF != null)
					if(mm.matrixF.length == 1)
						mm.matrixF[0][0].update();
					else
						mm.matrixF[x][y].update();
				
				mm.matrixS[x][y].update();
				
				if(mm.matrixR.length != 1)
					mm.matrixR[x][y].update();
				else
					mm.matrixR[0][0].update();
			}
	}

	@Override
	public void draw(Graphics2D g2d) {
		bg.draw(g2d);
		for(ParColchete inst: parColchetes)
			if(inst != null)
				inst.draw(g2d);
		for(SinaisOperacao inst: sinaisOperacao)
			if(inst != null)
				inst.draw(g2d);
		mm.draw(g2d);
		g2d.setFont(font1);
		g2d.setColor(Color.BLACK);
		fm = g2d.getFontMetrics();
		fontWidth = fm.stringWidth(typeMatriz);
		g2d.drawString(typeMatriz, 400 - fontWidth/2, 92);
		ButtonManager.getInstace().draw(g2d);
	}

	public static void CheckSelected()
	{
		if(mm.matrixF != null)
		{
			if(mm.matrixF.length != 1)
			{
				for (int x = 0; x < type; x++)
				{
					for (int y = 0; y < type; y++)
					{
						mm.matrixF[x][y].selected = false;
						if (mm.matrixF[x][y].clicked == true)
						{
							curS = new Point(x, y);
							mm.matrixF[x][y].selected = true;
							mNumber = 1;
						}
					}
				}
			}
			else
			{
				mm.matrixF[0][0].selected = false;
				if (mm.matrixF[0][0].clicked == true)
				{
					curS = new Point (0,0);
					mm.matrixF[0][0].selected = true;
					mNumber = 1;
				}
			}
		}
		
		for (int x = 0; x < type; x++)
		{
			for (int y = 0; y < type; y++)
			{
				mm.matrixS[x][y].selected = false;
				if (mm.matrixS[x][y].clicked == true)
				{
					curS = new Point(x, y);
					mm.matrixS[x][y].selected = true;
					mNumber = 2;
				}
			}
		}
	}
	
	public boolean AllFilled()
	{
		int count = 0;
		
		for (int x = 0; x < type; x++)
			for (int y = 0; y < type; y++)
			{
				if(mm.matrixF != null)
					if (mm.matrixF.length != 1 && mm.matrixF[x][y].value == null)
						count+=1;
				if (mm.matrixS[x][y].value == null)
					count+=1;
			}
		
		if (count == 0)
			return true;
			return false;
	}

	public void CriarColchetes()
	{
		
		String image = "/images/Sinais.png";
		Point2D size = new Point2D.Double(30, 30);
		int distancia2x2 = 125;
		int distancia3x3 = 190;

		if(MatrixType.getMatrixType().length == 2)
		{
			Point2D posSinal = new Point2D.Double(250, 285);
			Point2D posIgualdade = new Point2D.Double(505, 285);
			Point2D pos1 = new Point2D.Double(70, 250);
			Point2D pos2 = new Point2D.Double(320, 250);
			Point2D pos3 = new Point2D.Double(580, 250);
			
			switch(MatrixOperation.getTypeOperation())
			{
				case SOMAR:
					parColchetes[0] = new ParColchete(2, distancia2x2, pos1);
					parColchetes[1] = new ParColchete(2, distancia2x2, pos2);
					parColchetes[2] = new ParColchete(2, distancia2x2, pos3);
					sinaisOperacao[0] = new SinaisOperacao(image, posSinal, size, 	new Point2D.Double(0, 0),
																					new Point2D.Double(30, 30));
					
					sinaisOperacao[1] = new SinaisOperacao(image, posIgualdade, size, 	new Point2D.Double(90, 0),
																					new Point2D.Double(30, 30));
					
					break;
				case MULTIPLICAR_MATRIZES:
					parColchetes[0] = new ParColchete(2, distancia2x2, pos1);
					parColchetes[1] = new ParColchete(2, distancia2x2, pos2);
					parColchetes[2] = new ParColchete(2, distancia2x2, pos3);
					sinaisOperacao[0] = new SinaisOperacao(image, posSinal, size, 	new Point2D.Double(60, 0),
																					new Point2D.Double(30, 30));

					sinaisOperacao[1] = new SinaisOperacao(image, posIgualdade, size, 	new Point2D.Double(90, 0),
																						new Point2D.Double(30, 30));
					
					break;
				case SUBTRAIR:
					parColchetes[0] = new ParColchete(2, distancia2x2, pos1);
					parColchetes[1] = new ParColchete(2, distancia2x2, pos2);
					parColchetes[2] = new ParColchete(2, distancia2x2, pos3);
					sinaisOperacao[0] = new SinaisOperacao(image, posSinal, size, 	new Point2D.Double(30, 0),
																					new Point2D.Double(30, 30));

					sinaisOperacao[1] = new SinaisOperacao(image, posIgualdade, size, 	new Point2D.Double(90, 0),
																						new Point2D.Double(30, 30));
					break;
				case OPOSTA:
					parColchetes[0] = new ParColchete(2, distancia2x2, new Point2D.Double(200, 250));
					parColchetes[1] = new ParColchete(2, distancia2x2, new Point2D.Double(460, 250));
					sinaisOperacao[0] = new SinaisOperacao(image, new Point2D.Double(385, 285), size, 	new Point2D.Double(90, 0),
																										new Point2D.Double(30, 30));
					sinaisOperacao[1] = new SinaisOperacao(image, new Point2D.Double(609, 250), size, 	new Point2D.Double(150, 0),
							new Point2D.Double(30, 30));
					break;
				case MULTIPLICAR_NUMERO:
					parColchetes[0] = new ParColchete(2, distancia2x2, new Point2D.Double(320, 250));
					parColchetes[1] = new ParColchete(2, distancia2x2, new Point2D.Double(580, 250));
					sinaisOperacao[0] = new SinaisOperacao(image, posSinal, size, 	new Point2D.Double(60, 0),
																					new Point2D.Double(30, 30));

					sinaisOperacao[1] = new SinaisOperacao(image, posIgualdade, size, 	new Point2D.Double(90, 0),
																						new Point2D.Double(30, 30));
					break;
				case TRANSPOSTA:
					parColchetes[0] = new ParColchete(2, distancia2x2, new Point2D.Double(200, 250));
					parColchetes[1] = new ParColchete(2, distancia2x2, new Point2D.Double(460, 250));
					sinaisOperacao[0] = new SinaisOperacao(image, new Point2D.Double(385, 285), size, 	new Point2D.Double(90, 0),
																										new Point2D.Double(30, 30));
					
					sinaisOperacao[1] = new SinaisOperacao(image, new Point2D.Double(609, 250), size, 	new Point2D.Double(120, 0),
																										new Point2D.Double(30, 30));
					break;	
					
				case DETERMINANTE:
					parColchetes[0] = new ParColchete(2, distancia2x2, new Point2D.Double(220, 250));
					sinaisOperacao[0] = new SinaisOperacao(image, new Point2D.Double(405, 285), size, 	new Point2D.Double(90, 0),
																										new Point2D.Double(30, 30));
					
					
					break;
			}
			
		}
		else
		{
			Point2D posSinal = new Point2D.Double(230, 285);
			Point2D posIgualdade = new Point2D.Double(515, 285);	
			Point2D pos1 = new Point2D.Double(10, 225);
			Point2D pos2 = new Point2D.Double(270, 225);
			Point2D pos3 = new Point2D.Double(580, 225);
			
			switch(MatrixOperation.getTypeOperation())
			{
				case SOMAR:
					parColchetes[0] = new ParColchete(3, distancia3x3, pos1);
					parColchetes[1] = new ParColchete(3, distancia3x3, pos2);
					parColchetes[2] = new ParColchete(3, distancia3x3, pos3);
					sinaisOperacao[0] = new SinaisOperacao(image, posSinal, size, 	new Point2D.Double(0, 0),
																					new Point2D.Double(30, 30));

					sinaisOperacao[1] = new SinaisOperacao(image, posIgualdade, size, 	new Point2D.Double(90, 0),
																						new Point2D.Double(30, 30));

					
					break;
				case MULTIPLICAR_MATRIZES:
					parColchetes[0] = new ParColchete(3, distancia3x3, pos1);
					parColchetes[1] = new ParColchete(3, distancia3x3, pos2);
					parColchetes[2] = new ParColchete(3, distancia3x3, pos3);
					sinaisOperacao[0] = new SinaisOperacao(image, posSinal, size, 	new Point2D.Double(60, 0),
																					new Point2D.Double(30, 30));

					sinaisOperacao[1] = new SinaisOperacao(image, posIgualdade, size, 	new Point2D.Double(90, 0),
																						new Point2D.Double(30, 30));
					
					break;
				case SUBTRAIR:
					parColchetes[0] = new ParColchete(3, distancia3x3, pos1);
					parColchetes[1] = new ParColchete(3, distancia3x3, pos2);
					parColchetes[2] = new ParColchete(3, distancia3x3, pos3);
					sinaisOperacao[0] = new SinaisOperacao(image, posSinal, size, 	new Point2D.Double(30, 0),
																					new Point2D.Double(30, 30));

					sinaisOperacao[1] = new SinaisOperacao(image, posIgualdade, size, 	new Point2D.Double(90, 0),
																						new Point2D.Double(30, 30));

					break;
				case OPOSTA:
					parColchetes[0] = new ParColchete(3, distancia3x3, new Point2D.Double(110, 225));
					parColchetes[1] = new ParColchete(3, distancia3x3, new Point2D.Double(480, 225));
					
					sinaisOperacao[0] = new SinaisOperacao(image, new Point2D.Double(385, 285), size, 	new Point2D.Double(90, 0),
																										new Point2D.Double(30, 30));
					
					sinaisOperacao[1] = new SinaisOperacao(image, new Point2D.Double(690, 225), size, 	new Point2D.Double(150, 0),
																										new Point2D.Double(30, 30));
					break;
				case MULTIPLICAR_NUMERO:
					parColchetes[0] = new ParColchete(3, distancia3x3, new Point2D.Double(250, 225));
					parColchetes[1] = new ParColchete(3, distancia3x3, new Point2D.Double(550, 225));
					sinaisOperacao[0] = new SinaisOperacao(image, new Point2D.Double(posSinal.getX() - 30, posSinal.getY()), size, 	new Point2D.Double(60, 0),
																																	new Point2D.Double(30, 30));

					sinaisOperacao[1] = new SinaisOperacao(image, new Point2D.Double(posIgualdade.getX() - 25, posIgualdade.getY()), size, 	new Point2D.Double(90, 0),
																																			new Point2D.Double(30, 30));
					break;
				case TRANSPOSTA:
					parColchetes[0] = new ParColchete(3, distancia3x3, new Point2D.Double(110, 225));
					parColchetes[1] = new ParColchete(3, distancia3x3, new Point2D.Double(480, 225));
					
					
					sinaisOperacao[0] = new SinaisOperacao(image, new Point2D.Double(385, 285), size, 	new Point2D.Double(90, 0),
																										new Point2D.Double(30, 30));
					sinaisOperacao[1] = new SinaisOperacao(image, new Point2D.Double(690, 225), size, 	new Point2D.Double(120, 0),
																										new Point2D.Double(30, 30));
					break;	
				case DETERMINANTE:
					parColchetes[0] = new ParColchete(3, distancia3x3, new Point2D.Double(190, 225));
					sinaisOperacao[0] = new SinaisOperacao(image, new Point2D.Double(465, 285), size, 	new Point2D.Double(90, 0),
																										new Point2D.Double(30, 30));

					break;
			}
		}
		
		
	}

}
